/*
 * Determina las variables necesarias y funcionamiento para que el ServerGUI
 * la funcionalidad deseada.
 * CLASE SUSTRAIDA DE UNA PAGINA WEB
 */
package servclien;

import java.net.*;
import java.io.*;
import java.util.*;

public class Client {

    private ObjectInputStream _sInput;
    private ObjectOutputStream _sOutput;
    private Socket _socket;
    private ClientGUI _cg;
    private String server, username;
    private int port;

    /**
     *
     * Constructor utilizado para crear un nuevo cliente, pero haciendo uso de
     * la consola
     */
    Client(String pServer, int pPort, String pUsername) {
        this(pServer, pPort, pUsername, null);
    }

    /*
     * Constructor utilizado para crear un nuevo cliente, pero haciendo uso
     * de ServerGUI(representa una interfaz grafica )
     */
    Client(String pServer, int pPort, String pUsername, ClientGUI pCg) {
        this.server = pServer;
        this.port = pPort;
        this.username = pUsername;
        this._cg = pCg;
    }
        


    /**
     *
     * @return boolean indica si el cliente esta inicializado.
     */
    public boolean start() {
        try {
            _socket = new Socket(server, port);
        } catch (Exception ec) {
            display("Error connectiong to server:" + ec);
            return false;
        }
        String msg = "Connection accepted " + _socket.getInetAddress() + ":" + _socket.getPort();
        display(msg);
        try {
            _sInput = new ObjectInputStream(_socket.getInputStream());
            _sOutput = new ObjectOutputStream(_socket.getOutputStream());
        } catch (IOException eIO) {
            display("Exception creating new Input/output Streams: " + eIO);
            return false;
        }
        new ListenFromServer().start();
        try {
            _sOutput.writeObject(username);
        } catch (IOException eIO) {
            display("Exception doing login : " + eIO);
            disconnect();
            return false;
        }
        return true;
    }

    /**
     * Despliegue del mensaje de acuerdo al medio elegido interfaz o consola
     *
     * @param pMsg Mensaje que se deseea comunicar
     */
    private void display(String pMsg) {
        if (_cg == null) {
            System.out.println(pMsg);
        } else {
            _cg.append(pMsg + "\n");
        }
    }

    /**
     * Envio del mensaje
     * @param pMsg mensaje que se desea comunicar
     */
    void sendMessage(ChatMessage pMsg) {
        try {
            _sOutput.writeObject(pMsg);
        } 
        catch (IOException e) {
            display("Exception writing to server: " + e);
        }
    }
    
    /**
     *  Permite realizar la desconexion de un cliente del servidor.
     */
    private void disconnect() {
        try {
            if (_sInput != null) {
                _sInput.close();
            }
        } 
        catch (Exception e) {
        } 
        try {
            if (_sOutput != null) {
                _sOutput.close();
            }
        } 
        catch (Exception e) {
        } 
        try {
            if (_socket != null) {
                _socket.close();
            }
        } 
        catch (Exception e) {
        } 
        if (_cg != null) {
            _cg.connectionFailed();
        }

    }
    
    /**
     * Metodo que se ejecuta al ser ejecutado el archivo
     * @param pArgs 
     */

    public static void main(String[] pArgs) {
        int portNumber = 1500;
        String serverAddress = "localhost";
        String userName = "Anonymous";
        switch (pArgs.length) {
            case 3:
                serverAddress = pArgs[2];
            case 2:
                try {
                    portNumber = Integer.parseInt(pArgs[1]);
                } catch (Exception e) {
                    System.out.println("Invalid port number.");
                    System.out.println("Usage is: > java Client [username] [portNumber] [serverAddress]");
                    return;
                }
            case 1:
                userName = pArgs[0];
            case 0:
                break;
            default:
                System.out.println("Usage is: > java Client [username] [portNumber] {serverAddress]");
                return;
        }
        Client client = new Client(serverAddress, portNumber, userName);
        if (!client.start()) {
            return;
        }
        Scanner scan = new Scanner(System.in);
        while (true) {
            System.out.print("> ");
            String msg = scan.nextLine();
            if (msg.equalsIgnoreCase("LOGOUT")) {
                client.sendMessage(new ChatMessage(ChatMessage.LOGOUT, ""));
                break;
            } 
            else 
                if (msg.equalsIgnoreCase("WHOISIN")) {
                    client.sendMessage(new ChatMessage(ChatMessage._whoIsIn, ""));
                } 
                else {				
                    client.sendMessage(new ChatMessage(ChatMessage._messageNumber, msg));
                }
        }
        client.disconnect();
    }

    /**
     * clase del Thread del cliente que permita una constante y correcta comunicacion
     * con el servidor.
     */
    class ListenFromServer extends Thread {
        public void run() {
            while (true) {
                try {
                    String msg = (String) _sInput.readObject();
                    if (_cg == null) {
                        System.out.println(msg);
                        System.out.print("> ");
                    } 
                    else {
                        _cg.append(msg);
                    }
                } 
                catch (IOException e) {
                    display("Server has close the connection: " + e);
                    if (_cg != null) {
                        _cg.connectionFailed();
                    }
                    break;
                } 
                catch (ClassNotFoundException e2) {
                }
            }
        }
    }
}
